<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // ES5 对象取值和赋值给变量
    // var zhang = {name:"张三",age:18,height:"177cm",weight:"70kg"};

    // var name = zhang.name;
    // var age = zhang.age;
    // var height = zhang.height;
    // var weight = zhang.weight;


</script>
<script>
    // 解构赋值  
    // ES6 允许按照一定模式，从数组和对象中提取值，对变量进行赋值，这被称为解构 
    // 本质上，这种写法属于“模式匹配”，只要等号两边的模式相同，左边的变量就会被赋予对应的值。
    // 解构不仅可以用于数组，还可以用于对象。

    // 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的，变量的取值由它的位置决定；而对象的属性没有次序，变量必须与属性同名，才能取到正确的值

    // 对象解构: 模式匹配,对应键名取值 (对应键名解构,将健值赋值给对应的变量)

    var zhang = { name: "张三", age: 18, height: "177cm", weight: "70kg" };

    var { name, age, height, weight } = zhang;
    console.log(name, age, height, weight);

    // 等价于
    var { name: name, age: age, height: height, weight: weight } = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    console.log(name, age, height, weight);

    // 自定义变量名 (对应键名解构,将健值赋值给对应的变量)
    // (1) 如果变量已经被使用, 可以自定义变量名
    // (2) 对象的键名不能作为变量名 (是关键字/保留字 class delete var)
    var { "name": a, "age": b, height: c, weight: d } = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    console.log(a, b, c, d);

    var { name, age, class: cls, height, weight } = { name: "张三", age: 18, class: "2308", height: "177cm", weight: "70kg" };
    console.log(name, age, cls, height, weight); 


    // 完全解构
    var zhang = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    var { name, age, height, weight } = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    console.log(name, age, height, weight);

    // 不完全结构 (等号左边对应等号右边部分)
    var { name, age } = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    console.log(name, age);

    var { height,weight } = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    console.log(height,weight);

    // 解构不成功,(等号左边的变量,在等号右边没有对应的属性),默认返回undefined

    var { name, age, height, weight, sex } = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    console.log(name, age, height, weight, sex);

    // 在解构过程中设置默认值
    var { name, age, height, weight, sex = "secret" } = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    console.log(name, age, height, weight, sex);

    // 拓展应用
    // 对象解构 配合 扩展运算符 => Rest参数

    // 将剩余参数整合到新对象info中
    // var { name, age, ...info} = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    // console.log(name, age, info);


    // 报错: Rest参数必须放在最后一位
    // var { name, ...info,weight} = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    // console.log(name, weight);

    // 对象对应键名取值,排名部分先后
    // var { name,weight, ...info} = { name: "张三", age: 18, height: "177cm", weight: "70kg" };
    // console.log(name, weight,info);

    // 对象解构需要注意:  不能对null和undefined进行解构
    // var {a} = 1;   // num.toFixed(1)  num.toString(1)   number也是一个特殊的对象
    // console.log(a); // undefined

    // 报错
    // var {a} = null;
    // console.log(a); 


    // 对象解构高级: 
    // 小技巧: 如果需要对对象中的属性值(数组/对象)进行二次解构,需要对应键名解构健值
    var zhang = {
        name: "张三",
        age: 18,
        info: {
            height: "177cm",
            weight: "65kg",
        },
        grade: [55, 66, 77],
    }



    // (1) 拆分解构
    // var {name,age,info,grade} = zhang;
    // var {height,weight} = info;
    // var [a,b,c] = grade;

    // console.log(name,age,info,grade);
    // console.log(height,weight);
    // console.log(a,b,c);


    // (2) 一步到位
    // var {name,age,info:info,grade:grade} = zhang;
    var { name, age, info: { height, weight }, grade: [a, b, c] } = zhang;
    console.log(name, age, height, weight, a, b, c);

    var { name, age, info: { height, weight }, grade: [a, b, c] } = zhang;
    var { name, age, info: { height: h, weight: w }, grade: [a, b, c] } = zhang;



</script>

</html>